#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>

#include "log.hpp"
#include "Task.hpp"
#include "Thread.hpp"
#include "ThreadPool.hpp"

using namespace ThreadNs;
static const uint16_t gport = 8080;

class tcpServer
{
    enum
    {
        USAGE_ERR = 1,
        SOCKET_ERR,
        BIND_ERR,
        LISTEN_ERR
    };

    const static int gbacklog = 5;

    class ThreadData
    {
    public:
        ThreadData(tcpServer *self, int sock) : _self(self), _sock(sock)
        {
        }

    public:
        tcpServer *_self;
        int _sock;
    };

public:
    tcpServer(const uint16_t &port = gport)
        : _port(port), _listensock(-1)
    {
    }

    void initServer()
    {
        // 1. 创建socket文件套接字对象
        _listensock = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensock < 0)
        {
            logMessage(FATAL, "create socket error");
            exit(SOCKET_ERR);
        }
        logMessage(NORMAL, "create socket success:%d", _listensock);

        // 2. bind绑定自己的网络信息
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = INADDR_ANY;

        int n = bind(_listensock, (struct sockaddr *)&local, sizeof(local));
        if (n < 0)
        {
            logMessage(FATAL, "bind socket error");
            exit(BIND_ERR);
        }
        logMessage(NORMAL, "bind socket success");

        // 3. 设置socket 为监听状态
        n = listen(_listensock, gbacklog);
        if (n < 0)
        {
            logMessage(FATAL, "listen socket error");
            exit(LISTEN_ERR);
        }
        logMessage(NORMAL, "listen socket success");
    }

    // version 1
    // void start()
    // {
    //     for (;;)
    //     {
    //         // 4. server 获取新链接
    //         struct sockaddr_in peer;
    //         socklen_t len = sizeof(peer);
    //         int sock = accept(_listensock, (struct sockaddr *)&peer, &len);
    //         if (sock < 0)
    //         {
    //             logMessage(ERROR, "accetpt error,next");
    //             continue;
    //         }
    //         logMessage(NORMAL, "accept a new link success, get new sock: %d", sock);

    //         // version 1
    //         serviceIO(sock);
    //         close(sock);
    //     }
    // }

    // 2 多进程版(2)
    // void start()
    // {
    //     signal(SIGCHLD, SIG_IGN);
    //     for (;;)
    //     {
    //         // 4. server 获取新链接
    //         struct sockaddr_in peer;
    //         socklen_t len = sizeof(peer);
    //         int sock = accept(_listensock, (struct sockaddr *)&peer, &len);
    //         if (sock < 0)
    //         {
    //             logMessage(ERROR, "accetpt error,next");
    //             continue;
    //         }
    //         logMessage(NORMAL, "accept a new link success, get new sock: %d", sock);

    //         // version 2 多进程版(2)
    //         pid_t id = fork();
    //         if (id == 0)
    //         {
    //             close(_listensock);
    //             // if (fork() > 0)
    //             //     exit(0);
    //             serviceIO(sock);
    //             close(sock);
    //             exit(0);
    //         }

    //         pid_t ret = waitpid(id, nullptr, 0);
    //         if (ret > 0)
    //         {
    //             std::cout << "wait sucess " << ret << std::endl;
    //         }
    //     }
    // }

    void start()
    {
        // ThreadPool<Task>::getInstance()->run();
        // logMessage(NORMAL, "Thread init success");
        for (;;)
        {
            // 4. server 获取新链接
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int sock = accept(_listensock, (struct sockaddr *)&peer, &len);
            if (sock < 0)
            {
                logMessage(ERROR, "accetpt error,next");
                continue;
            }
            logMessage(NORMAL, "accept a new link success, get new sock: %d", sock);

            pthread_t tid;
            ThreadData *td = new ThreadData(this, sock);

            pthread_create(&tid, nullptr, threadRoutine, td);
            pthread_join(tid, nullptr);

            // version4 线程池
            // ThreadPool<Task>::getInstance()->push(Task(sock, serviceIO));
        }
    }

    static void *threadRoutine(void *args)
    {
        pthread_detach(pthread_self());
        ThreadData *td = static_cast<ThreadData *>(args);
        td->_self->serviceIO(td->_sock);
        close(td->_sock);
        delete td;

        return nullptr;
    }

    void serviceIO(int sock)
    {
        char buffer[1024];
        while (true)
        {
            ssize_t n = read(sock, buffer, sizeof(buffer) - 1);
            if (n > 0)
            {
                // 目前我们把读到的数据当成字符串
                buffer[n] = 0;
                std::cout << "recv message: " << buffer << std::endl;

                std::string outbuffer = buffer;
                outbuffer += "[server echo]";
                write(sock, outbuffer.c_str(), outbuffer.size());
            }
            else if (n == 0)
            {
                // 代表client退出
                logMessage(NORMAL, "client quit, me too!");
                break;
            }
        }
        close(sock);
    }
    ~tcpServer()
    {
    }

private:
    int _listensock;
    uint16_t _port;
};
